<!DOCTYPE html>
<script src="../../resources/js-test.js"></script>
<div id="description"></div>
<div id="console"></div>
<script>
// http://heycam.github.io/webidl/#es-operations
description('Operations that return a Promise type should handle exceptions ' +
            'by returning a rejected Promise with the exception.')

window.jsTestIsAsync = true;

var reason;

function shouldBeRejected(promise, message) {
    return promise.then(function() {
        testFailed('Resolved unexpectedly: ' + message);
    }, function(e) {
        reason = e;
        testPassed('Rejected as expected: ' + message);
        shouldBeTrue('reason instanceof Error');
        debug(e);
    });
}

function shouldBeResolved(promise, message) {
    return promise.then(function() {
        testPassed('Resolved as expected: ' + message);
    }, function(e) {
        testFailed('Rejected unexpectedly: ' + message);
        reason = e;
        shouldBeTrue('reason instanceof Error');
        debug(e);
    });
}

var check = internals.promiseCheck.bind(internals);
var check2 = internals.promiseCheckWithoutExceptionState.bind(internals);
var check3 = internals.promiseCheckRange.bind(internals);
var check4 = internals.promiseCheckOverload.bind(internals);

Promise.resolve().then(function() {
    return shouldBeRejected(check(), 'no arguments');
}).then(function() {
    return shouldBeResolved(check(3, true, {}, '', ['']), 'valid arguments');
}).then(function() {
    return shouldBeResolved(check(null, true, {}, '', []), 'convert(long)');
}).then(function() {
    return shouldBeResolved(check(3, {}, {}, '', []), 'convert(boolean)');
}).then(function() {
    return shouldBeRejected(check(3, true, 3, '', []), 'type error(Dictionary)');
}).then(function() {
    return shouldBeResolved(check(3, true, {}, {}, []), 'convert(String)');
}).then(function() {
    var x = {
        toString: function() {
            throw Error('Thrown from toString');
        }
    };
    return shouldBeRejected(check(3, true, {}, x, []), 'conversion error(toString)');
}).then(function() {
    var x = {
        toString: function() {
            throw Error('Thrown from toString');
        }
    };
    return shouldBeRejected(check(3, true, {}, '', [x]), 'conversion error([String])');
}).then(function() {
    return shouldBeRejected(check(3, false, {}, '', []), 'rejected by the impl');
}).then(function() {
    return shouldBeRejected(check2(), 'no arguments');
}).then(function() {
    return shouldBeResolved(check2({}, '', '', ''), 'valid arguments');
}).then(function() {
    return shouldBeResolved(check2({}, ''), 'valid arguments');
}).then(function() {
    return shouldBeRejected(check2(3, ''), 'type error(Dictionary)');
}).then(function() {
    return shouldBeResolved(check2({}, '', {}, 3), 'convert(String...)');
}).then(function() {
    var x = {
        toString: function() {
            throw Error('Thrown from toString');
        }
    };
    return shouldBeRejected(check2({}, '', '', x), 'conversion error(String...)');
}).then(function() {
    return shouldBeRejected(check3(-1), 'range error(octet)');
}).then(function() {
    return shouldBeResolved(check4(location), 'valid argument (Location)');
}).then(function() {
    return shouldBeResolved(check4(document), 'valid argument (Document)');
}).then(function() {
    return shouldBeResolved(check4(location, 0, 0), 'valid argument (Location, long, long)');
}).then(function() {
    return shouldBeRejected(check4({}), 'type error (Object)');
}).then(function() {
    return shouldBeRejected(check4(location, 0), 'type error (Location, long)');
}).then(undefined, function(e) {
    testFailed('An exception is thrown from a method');
    debug(e);
}).then(finishJSTest, finishJSTest);
</script>
